<template>
  <div class="pdf-preview-page">
    <!-- 加载状态 -->
    <div v-if="isLoading" class="loading-container">
      <div class="loading-content">
        <div class="loading-spinner"></div>
        <p>正在加载PDF图片...</p>
      </div>
    </div>
    <!-- PDF图片查看器 -->
    <PdfImageViewer
        v-else
        :imageUrls="imageUrls"
        :totalPages="totalPages"
        :coverData="coverData"
        :tableOfContents="tableOfContents"
        :materialPageCounts="materialPageCounts"
        @generatePdf="handleGeneratePdf"
        @editCover="handleEditCover"
        @goBack="handleGoBack"
        style="margin-top: 30px;"
    />
    <!-- 封面编辑器弹窗 -->
    <CoverEditor
        v-if="showCoverEditor"
        :visible="showCoverEditor"
        :initialCoverData="coverData"
        @update:visible="showCoverEditor = $event"
        @confirm="handleCoverEditorConfirm"
        @cancel="handleCoverEditorCancel"
    />
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage, ElLoading } from 'element-plus'
import PdfImageViewer from '@/components/academic/PdfImageViewer.vue'
import CoverEditor from '@/components/CoverEditor.vue'
import {getPdfImages, saveMaterialHistory} from '@/api/Assistants/material.js'
// 引入 pdf-lib
import { PDFDocument, PageSizes } from 'pdf-lib'

const router = useRouter()
const route = useRoute()

// 响应式数据
const isLoading = ref(true)
const imageUrls = ref([])
const totalPages = ref(0)
const showCoverEditor = ref(false)
const materialPageCounts = ref([])

// 从路由参数获取项目信息
const thesisInfo = ref({
  projectName: route.query.projectName || '',
  projectLevel: route.query.projectLevel || '',
  projectNumber: route.query.projectNumber || '',
  startTime: route.query.startTime || '',
  projectStatus: route.query.projectStatus || '',
  results: JSON.parse(route.query.results || '[]')
})

// 封面数据
const coverData = ref({
  contentItems: [],
  font: 'SimHei, 黑体',
  declarationInfo: {
    person: '',
    unit: '',
    position: { y: 500 }, // 申报信息位置（已调整为更靠下）
    labels: {
      person: '申报人',
      unit: '申报单位'
    }
  }
})

// 目录数据
const tableOfContents = ref([])

// 获取字体大小的辅助函数
const getFontSize = (type) => {
  switch (type) {
    case 'h1': return '32px'
    case 'h2': return '24px'
    case 'h3': return '20px'
    default: return '16px'
  }
}

// 初始化数据
const initData = () => {
  coverData.value.contentItems = [
    {
      id: Date.now(),
      type: 'h1',
      text: '附件材料',
      position: { y: 100 }
    }
  ];
  coverData.value.declarationInfo.position.y = 500; // 申报信息位置初始化（已调整）
  if (thesisInfo.value.results && thesisInfo.value.results.length > 0) {
    tableOfContents.value = thesisInfo.value.results.map((item, index) => ({
      title: `${item.type}: ${item.title}`,
      originalIndex: index
    }))
  }
}

// 加载所有图片
const loadAllImages = async () => {
  try {
    isLoading.value = true
    const allImageUrls = []
    const pageCounts = []
    for (const result of thesisInfo.value.results) {
      if (result.pdfUrl) {
        console.log(`正在加载: ${result.title}`)
        try {
          const response = await getPdfImages(result.pdfUrl)
          console.log(`${result.title} 响应:`, response)
          if (response.code === "0" && response.data.imageUrls) {
            allImageUrls.push(...response.data.imageUrls)
            pageCounts.push(response.data.pageCount || response.data.imageUrls.length)
            console.log(`${result.title} 加载成功，页数: ${response.data.pageCount || response.data.imageUrls.length}`)
          } else {
            pageCounts.push(0)
            console.warn(`${result.title} 加载失败`)
          }
        } catch (error) {
          console.error(`加载 ${result.title} 的图片失败:`, error)
          ElMessage.warning(`${result.title} 的图片加载失败`)
          pageCounts.push(0)
        }
      } else {
        pageCounts.push(0)
      }
    }
    imageUrls.value = allImageUrls
    totalPages.value = allImageUrls.length
    materialPageCounts.value = pageCounts
    console.log('材料页数信息:', pageCounts)
    console.log('总图片数:', allImageUrls.length)
    if (allImageUrls.length === 0) {
      ElMessage.warning('没有找到可显示的图片')
    }
  } catch (error) {
    console.error('加载图片失败:', error)
    ElMessage.error('加载PDF图片失败，请稍后重试')
  } finally {
    isLoading.value = false
  }
}

// 生成PDF并上传
const handleGeneratePdf = async () => {
  if (imageUrls.value.length === 0) {
    ElMessage.warning('没有可生成的内容');
    return;
  }

  const loadingInstance = ElLoading.service({
    lock: true,
    text: '正在生成并上传PDF...', // 修改加载提示
    background: 'rgba(255, 255, 255, 0.7)',
  });

  try {
    const newPdfDoc = await PDFDocument.create();
    const A4_WIDTH = PageSizes.A4[0];
    const A4_HEIGHT = PageSizes.A4[1];
    // DPI_SCALE 用于 canvas 绘制，确保清晰度
    const DPI_SCALE = 3;
    // A4尺寸像素值
    const A4_WIDTH_PX = (210 / 25.4) * 96 * DPI_SCALE;
    const A4_HEIGHT_PX = (297 / 25.4) * 96 * DPI_SCALE;
    // 预览器宽度（公共作用域）
    const VIEWER_WIDTH_PX = 595;

    // --- 1. 生成封面页 ---
    const coverPage = newPdfDoc.addPage(PageSizes.A4);
    const coverCanvas = document.createElement('canvas');
    coverCanvas.width = A4_WIDTH_PX;
    coverCanvas.height = A4_HEIGHT_PX;
    const ctx = coverCanvas.getContext('2d');
    ctx.fillStyle = 'white';
    ctx.fillRect(0, 0, coverCanvas.width, coverCanvas.height);

    // 加载字体
    // 注意：这里假设浏览器能访问到系统字体，如果需要自定义字体，需要额外处理字体嵌入
    await document.fonts.load(`16px ${coverData.value.font}`);

    // 绘制动态内容项
    coverData.value.contentItems.forEach(item => {
      const fontSizePx = parseFloat(getFontSize(item.type)) * DPI_SCALE;
      ctx.font = `${fontSizePx}px ${coverData.value.font}`;
      ctx.textAlign = 'center';
      ctx.fillStyle = 'black';
      const yPx = (item.position.y / 842) * A4_HEIGHT_PX;
      ctx.fillText(item.text, coverCanvas.width / 2, yPx);
    });

    // 绘制申报信息（文本居中逻辑强化）
    if (coverData.value.declarationInfo) {
      const declarationInfo = coverData.value.declarationInfo;
      // 基础字体大小（用于输入内容）
      const baseFontSizePx = parseFloat(getFontSize('text')) * DPI_SCALE;
      // 标签字体大小（放大20%，可根据需要调整比例）
      const labelFontSizePx = baseFontSizePx * 1.2;
      ctx.fillStyle = 'black';
      ctx.textBaseline = 'middle';

      // 基于预览器宽度的尺寸定义
      const DECLARATION_BLOCK_WIDTH_VIEWER_PX = 300;
      // 关键：固定标签宽度，确保文本在内部对齐
      const LABEL_WIDTH_VIEWER_PX = 100; // 缩小标签宽度，强制文本居中对齐
      const GAP_VIEWER_PX = 15;
      const FIXED_VALUE_INPUT_WIDTH_VIEWER_PX = 135;

      // 计算缩放后的尺寸
      const declarationBlockWidthPx = (DECLARATION_BLOCK_WIDTH_VIEWER_PX / VIEWER_WIDTH_PX) * A4_WIDTH_PX;
      const labelWidthPx = (LABEL_WIDTH_VIEWER_PX / VIEWER_WIDTH_PX) * A4_WIDTH_PX;
      const gapPx = (GAP_VIEWER_PX / VIEWER_WIDTH_PX) * A4_WIDTH_PX;
      const valueAreaWidthPx = (FIXED_VALUE_INPUT_WIDTH_VIEWER_PX / VIEWER_WIDTH_PX) * A4_WIDTH_PX;

      // 计算位置
      const declarationBlockStartX = (coverCanvas.width / 2) - (declarationBlockWidthPx / 2);
      const valueAreaStartX = declarationBlockStartX + labelWidthPx + gapPx;
      const declarationYPx = (declarationInfo.position.y / 842) * A4_HEIGHT_PX;

      // 调整下划线偏移量以适应更大字体
      const underlineOffsetFromTextMiddle = (baseFontSizePx / 2) + (2 * DPI_SCALE);

      // 绘制申报人信息（拆字单独绘制，精准控制间距）
      ctx.textAlign = 'right';
      // 标签使用放大后的字体
      ctx.font = `${labelFontSizePx}px ${coverData.value.font}`;
      // 方式三：拆字绘制，手动控制每个字的间距（单位：像素，可自定义）
      const charSpacing = 5; // 每个字之间的间距（像素），想缩小就改小，比如 3
      const chars = [':', '人', '报', '申'];
      // 计算第一个字的起始位置（右对齐，从标签右边缘往左排）
      let x = declarationBlockStartX + labelWidthPx;
      for (let i = 0; i < chars.length; i++) {
        const char = chars[i];
        // 测量当前字的宽度（用于精准定位）
        const charWidth = ctx.measureText(char).width;
        // 绘制当前字：每次向左偏移“字宽 + 自定义间距”
        ctx.fillText(char, x - charWidth, declarationYPx);
        // 更新下一个字的 X 坐标（向左移动）
        x -= (charWidth + charSpacing);
      }

      // 输入内容使用原字体大小
      ctx.font = `${baseFontSizePx}px ${coverData.value.font}`;
      ctx.textAlign = 'center';
      const personValueTextX = valueAreaStartX + (valueAreaWidthPx / 2);
      if (declarationInfo.person) {
        ctx.fillText(declarationInfo.person, personValueTextX, declarationYPx);
      }
      // 申报人下划线
      ctx.beginPath();
      ctx.strokeStyle = 'black';
      ctx.lineWidth = 1 * DPI_SCALE;
      const personUnderlineY = declarationYPx + underlineOffsetFromTextMiddle;
      ctx.moveTo(valueAreaStartX, personUnderlineY);
      ctx.lineTo(valueAreaStartX + valueAreaWidthPx, personUnderlineY);
      ctx.stroke();

      // 绘制申报单位信息（标签字体放大）
      // 调整行间距以适应更大字体
      const nextLineYPx = declarationYPx + baseFontSizePx * 2.3;
      ctx.textAlign = 'right';
      // 标签使用放大后的字体
      ctx.font = `${labelFontSizePx}px ${coverData.value.font}`;
      ctx.fillText(
          `${declarationInfo.labels.unit}：`,
          declarationBlockStartX + labelWidthPx, // 与申报人标签右边缘对齐
          nextLineYPx
      );

      // 输入内容使用原字体大小
      ctx.font = `${baseFontSizePx}px ${coverData.value.font}`;
      ctx.textAlign = 'center';
      const unitValueTextX = valueAreaStartX + (valueAreaWidthPx / 2);
      if (declarationInfo.unit) {
        ctx.fillText(declarationInfo.unit, unitValueTextX, nextLineYPx);
      }
      // 申报单位下划线
      ctx.beginPath();
      ctx.strokeStyle = 'black';
      ctx.lineWidth = 1 * DPI_SCALE;
      const unitUnderlineY = nextLineYPx + underlineOffsetFromTextMiddle;
      ctx.moveTo(valueAreaStartX, unitUnderlineY);
      ctx.lineTo(valueAreaStartX + valueAreaWidthPx, unitUnderlineY);
      ctx.stroke();
    }

    // 嵌入封面图片
    const coverImageBytes = await new Promise((resolve) => {
      coverCanvas.toBlob((blob) => {
        const reader = new FileReader();
        reader.onload = () => resolve(new Uint8Array(reader.result));
        reader.readAsArrayBuffer(blob);
      }, 'image/png', 1.0);
    });
    const coverImage = await newPdfDoc.embedPng(coverImageBytes);
    coverPage.drawImage(coverImage, {
      x: 0,
      y: 0,
      width: A4_WIDTH,
      height: A4_HEIGHT,
    });

    // --- 2. 生成目录页 ---
    const tocPage = newPdfDoc.addPage(PageSizes.A4);
    const tocCanvas = document.createElement('canvas');
    tocCanvas.width = A4_WIDTH_PX;
    tocCanvas.height = A4_HEIGHT_PX;
    const tocCtx = tocCanvas.getContext('2d');
    tocCtx.fillStyle = 'white';
    tocCtx.fillRect(0, 0, tocCanvas.width, tocCanvas.height);

    tocCtx.font = `${parseFloat(getFontSize('h2')) * DPI_SCALE}px ${coverData.value.font}`;
    tocCtx.fillStyle = 'black';
    tocCtx.textAlign = 'center';
    tocCtx.fillText('目录', tocCanvas.width / 2, (40 / 842) * A4_HEIGHT_PX);

    tocCtx.font = `${parseFloat(getFontSize('text')) * DPI_SCALE}px ${coverData.value.font}`;
    tocCtx.textAlign = 'left';
    let currentYPx = (60 / 842) * A4_HEIGHT_PX;
    const lineHeightPx = parseFloat(getFontSize('text')) * DPI_SCALE * 1.5;

    // 计算页码
    let currentPdfPageNumber = 3; // 封面1页 + 目录1页 = 2页，所以内容从第3页开始
    const materialPageStart = [];
    for (let i = 0; i < materialPageCounts.value.length; i++) {
      materialPageStart.push(currentPdfPageNumber);
      currentPdfPageNumber += materialPageCounts.value[i];
    }

    // 绘制目录项
    tableOfContents.value.forEach((item, index) => {
      if (currentYPx > A4_HEIGHT_PX - (20 * DPI_SCALE)) {
        // 超出页面范围的处理（简化版，实际应用可能需要分页）
        // 这里可以添加新页面并继续绘制目录
      }
      const pageNumber = materialPageStart[index];
      const text = `${item.title}`;
      const pageNumText = `${pageNumber}`;

      // 绘制标题
      tocCtx.fillText(text, (20 / VIEWER_WIDTH_PX) * A4_WIDTH_PX, currentYPx);
      // 绘制页码
      tocCtx.textAlign = 'right';
      tocCtx.fillText(pageNumText, A4_WIDTH_PX - (20 / VIEWER_WIDTH_PX) * A4_WIDTH_PX, currentYPx);
      tocCtx.textAlign = 'left';
      currentYPx += lineHeightPx;
    });

    // 嵌入目录图片
    const tocImageBytes = await new Promise((resolve) => {
      tocCanvas.toBlob((blob) => {
        const reader = new FileReader();
        reader.onload = () => resolve(new Uint8Array(reader.result));
        reader.readAsArrayBuffer(blob);
      }, 'image/png', 1.0);
    });
    const tocImage = await newPdfDoc.embedPng(tocImageBytes);
    tocPage.drawImage(tocImage, {
      x: 0,
      y: 0,
      width: A4_WIDTH,
      height: A4_HEIGHT,
    });

    // --- 3. 添加图片页面 ---
    for (const imageUrl of imageUrls.value) {
      try {
        const response = await fetch(imageUrl, {
          mode: 'cors',
          credentials: 'omit',
          headers: { 'Accept': 'image/*' }
        });
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status} for ${imageUrl}`);
        }
        const imageBlob = await response.blob();
        const imageBytes = await imageBlob.arrayBuffer();

        const loadedImg = await new Promise((resolve, reject) => {
          const img = new Image();
          img.crossOrigin = "anonymous"; // 解决CORS问题
          img.onload = () => {
            URL.revokeObjectURL(img.src);
            resolve(img);
          };
          img.onerror = () => {
            URL.revokeObjectURL(img.src);
            reject(new Error(`加载图片失败: ${imageUrl}`));
          };
          img.src = URL.createObjectURL(imageBlob);
        });

        const imgWidth = loadedImg.naturalWidth;
        const imgHeight = loadedImg.naturalHeight;

        const page = newPdfDoc.addPage(PageSizes.A4);
        const ratio = Math.min(A4_WIDTH / imgWidth, A4_HEIGHT / imgHeight);
        const finalWidth = imgWidth * ratio;
        const finalHeight = imgHeight * ratio;
        const x = (A4_WIDTH - finalWidth) / 2;
        const y = (A4_HEIGHT - finalHeight) / 2;

        let embeddedImage;
        if (imageBlob.type === 'image/png') {
          embeddedImage = await newPdfDoc.embedPng(imageBytes);
        } else if (imageBlob.type === 'image/jpeg') {
          embeddedImage = await newPdfDoc.embedJpg(imageBytes);
        } else {
          // 尝试根据URL后缀判断，作为备用
          const urlLower = imageUrl.toLowerCase();
          if (urlLower.endsWith('.png')) {
            embeddedImage = await newPdfDoc.embedPng(imageBytes);
          } else {
            embeddedImage = await newPdfDoc.embedJpg(imageBytes);
          }
        }
        page.drawImage(embeddedImage, { x, y, width: finalWidth, height: finalHeight });
      } catch (error) {
        console.error(`处理图片失败 ${imageUrl}:`, error);
      }
    }

    // 生成PDF的字节数据
    const finalPdfBytes = await newPdfDoc.save();
    const pdfBlob = new Blob([finalPdfBytes], { type: 'application/pdf' });
    const fileName = `${thesisInfo.value?.projectName || '附件材料'}.pdf`;

    // --- 上传PDF到后端 ---
    const formData = new FormData();
    formData.append('file', pdfBlob, fileName); // 'file' 必须与后端 @RequestParam("file") 的名称一致



    const uploadResponse = await saveMaterialHistory(formData);

    const result = uploadResponse;
    console.log("上传结果", result)

    if (result.code === 1) {
      ElMessage.success('PDF已生成并成功上传！');
      // 成功上传后，可以选择是否继续下载到本地
      const downloadUrl = URL.createObjectURL(pdfBlob);
      const a = document.createElement('a');
      a.href = downloadUrl;
      a.download = fileName;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(downloadUrl);
    } else {
      throw new Error(`文件上传失败: ${result.message || '后端返回错误'}`);
    }

  } catch (error) {
    console.error('生成或上传PDF失败:', error);
    ElMessage.error(`操作失败: ${error.message}`);
  } finally {
    loadingInstance.close();
  }
}

// 编辑封面
const handleEditCover = () => {
  console.log('打开封面编辑器，当前封面数据:', coverData.value)
  showCoverEditor.value = true
}

// 封面编辑确认
const handleCoverEditorConfirm = (data) => {
  coverData.value = data;
  nextTick(() => {
    console.log('封面数据更新完成');
  });
  showCoverEditor.value = false;
  ElMessage.success('封面信息已更新');
}

// 封面编辑取消
const handleCoverEditorCancel = () => {
  showCoverEditor.value = false
}

// 返回上一步
const handleGoBack = () => {
  router.back()
}

// 组件挂载时初始化
onMounted(() => {
  initData()
  loadAllImages()
})
</script>

<style scoped>
.pdf-preview-page {
  height: 105vh;
  overflow: hidden;
}
.loading-container {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 105vh;
  background-color: #f5f5f5;
}
.loading-content {
  text-align: center;
}
.loading-spinner {
  width: 48px;
  height: 48px;
  border: 4px solid #f3f3f3;
  border-top: 4px solid #00b96b;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin: 0 auto 16px;
}
@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
.loading-content p {
  color: #666;
  font-size: 16px;
  margin: 0;
}
</style>
